/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package hadss.adaptive_video

import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import io.flutter.plugin.common.EventChannel
import kotlin.math.atan2

/**
 * 重力感应，获取设备手持方向
 */
class GravityOrientationStreamHandler(
    private val sensorManager: SensorManager,
    private var interval: Int = SensorManager.SENSOR_DELAY_NORMAL,
) : EventChannel.StreamHandler, SensorEventListener {
    private val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
    private var eventSink: EventChannel.EventSink? = null
    private var lastOrientation = -1
    private var callback: ((Int) -> Unit)? = null

    override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        if (sensor != null) {
            eventSink = events
            sensorManager.registerListener(this, sensor, interval)
        }
    }

    override fun onCancel(arguments: Any?) {
        sensorManager.unregisterListener(this)
        eventSink = null
    }

    override fun onSensorChanged(event: SensorEvent?) {
        val values: FloatArray = floatArrayOf(event!!.values[0], event.values[1], event.values[2])
        val x: Float = values[0]
        val y: Float = values[1]
        val z: Float = values[2]
        val angle = calculateDegree(x, y, z)
        var orientation: Int = -1
        if (angle >= 0 && (angle <= 30 || angle >= 330)) {
            // 竖屏向上
            orientation = 0
        } else if (angle in 60..120) {
            // 横屏向右
            orientation = 1
        } else if (angle in 150..210) {
            // 反向竖屏
            orientation = 2
        } else if (angle in 240..300) {
            // 反向横屏
            orientation = 3
        }
        if (orientation != lastOrientation) {
            lastOrientation = orientation
            callback?.invoke(orientation)
            eventSink?.success(lastOrientation)
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    }

    fun setUpdateInterval(interval: Int) {
        this.interval = interval
        if (eventSink != null) {
            sensorManager.unregisterListener(this)
            sensorManager.registerListener(this, sensor, interval)
        }
    }

    fun addOrientationChangedListener(callback: (Int) -> Unit) {
        this.callback = callback
    }

    fun removeOrientationChangedListener() {
        callback = null
    }

    private fun calculateDegree(x: Float, y: Float, z: Float): Int {
        var angle: Int = -1
        if ((x * x + y * y) * 3 < z * z) {
            return angle
        }
        angle = 90 - Math.round(atan2(-y, x) / Math.PI * 180).toInt()
        return if (angle >= 0) angle % 360 else angle % 360 + 360
    }
}